﻿using System;
using System.Diagnostics;

namespace LuaVM.Core.Builtin
{
	class ProcessFuncs
	{
		private LuaEnv m_lua = null;

		public ProcessFuncs(LuaEnv lua)
		{
			m_lua = lua;
			lua.NewTable("process");
			lua.RegisterFunction<ProcessFuncs>("Find", "process.find");
			lua.RegisterFunction<ProcessFuncs>("Kill", "process.kill");			
		}

		/// <summary>
		/// 在lua环境实现线程睡眠
		/// </summary>
		/// <param name="milliseconds">睡眠毫秒数</param>
		public static void Sleep(int milliseconds)
		{
			System.Threading.Thread.Sleep(milliseconds);
		}		

		/// <summary>
		/// 查找进程
		/// </summary>
		/// <param name="arg1">查找参数（无/数字/字符串）</param>
		/// <returns>进程列表或null</returns>
		public object Find(object arg1 = null)
		{
			Process[] procs = null;

			// 无参数，返回所有进程
			if (arg1 == null)
			{
				try
				{
					procs = Process.GetProcesses();
				}
				catch
				{
				}
			}

			string type = arg1.GetType().Name;

			// 数字参数，进程ID
			if (type == "Double")
			{
				try
				{
					Process proc = Process.GetProcessById((int)arg1);
					if (proc != null)
					{
						procs = new Process[] { proc };
					}
				}
				catch
				{
				}
			}

			// 字符串参数，进程名
			if (type == "String")
			{
				try
				{
					procs = Process.GetProcessesByName(arg1.ToString());
				}
				catch
				{
				}
			}

			if (procs == null || procs.Length == 0)
			{
				return null;
			}

			ProcResult[] results = ProcResult.FromProcesses(procs);
			LuaTable table = m_lua.NewTable();
			table.CopyArray(results);
			return table.Table;
		}			

		public static int Kill(object arg1)
		{
			Type type = arg1.GetType();
			if (type.Name == "String")
			{
				try
				{
					Process[] procs = Process.GetProcessesByName(arg1.ToString());
					foreach (Process proc in procs)
					{
						proc.Kill();
					}

					return procs.Length;
				}
				catch 
				{
					return 0;
				}
			}

			try
			{
				Process proc = Process.GetProcessById((int)arg1);
				proc.Kill();
				return 1;
			}
			catch
			{
				return 0;
			}			
		}			
	}

	class ProcResult
	{
		public int Id { get; set; }
		public string ProcessName { get; set; }
		public string FileName { get; set; }
		public string Arguments { get; set; }
		public IntPtr MainWindowHandle { get; set; }
		public string MainWindowTitle { get; set; }

		public static ProcResult FromProcess(Process proc)
		{
			if (proc == null)
			{
				return null;
			}

			ProcResult result = new ProcResult()
			{
				Id = proc.Id,
				ProcessName = proc.ProcessName,
				FileName = proc.StartInfo.FileName,
				Arguments = proc.StartInfo.Arguments,
				MainWindowHandle = proc.MainWindowHandle,
				MainWindowTitle = proc.MainWindowTitle,
			};

			return result;
		}	
		
		public static ProcResult[] FromProcesses(Process[] procs)
		{
			if (procs == null)
			{
				return null;
			}

			ProcResult[] results = new ProcResult[procs.Length];
			for (int i = 0; i < procs.Length; i++)
			{
				results[i] = FromProcess(procs[i]);
			}

			return results;
		}
	}
}
